package com.xneure.database.sql.handler;

import java.util.Map.Entry;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import com.xneure.database.DynamicDataSource;
import com.xneure.database.annotation.AutoUpdate;
import com.xneure.database.dao.DataBaseTable;
import com.xneure.database.dao.TableValueCompare;
import com.xneure.database.metaobject.FieldMetaObject;
import com.xneure.database.metaobject.TableMetaObject;
import com.xneure.database.sql.SqlMapping;
import com.xneure.utils.ObjectUtil;

public class UpdateHandler extends SqlHandler{
	private StringBuilder sql = new StringBuilder("UPDATE ");
	private StringBuilder where = new StringBuilder(" WHERE ");
	private List<OutreachProvider> outreachHandlers;

	public UpdateHandler(){
		setSqlAspect(new SqlAspect(){
		});
	}

	@Override
	public void resetParam(){
		sql.setLength(7);
		where.setLength(7);
	}

	@Override
	public void addParam(String name,Object value){
		where.append(name).append(" = ").append(value);
	}

	@Override
	public String getSql(){
		String concat;
		if(where.length() > 7){
			concat = sql.toString().concat(where.toString());
		}else{
			concat = sql.toString();
		}
		if(outreachHandlers != null){
			StringBuilder sBuilder = new StringBuilder(concat);
			sBuilder.append(";\r\n");
			for(OutreachProvider oh:outreachHandlers){
				sBuilder.append(oh.buildSql());
			}
			concat = DynamicDataSource.getSqlDialect().batchSql(sBuilder.toString());
		}
		return concat;
	}

	@Override
	public void addWhere(String where){
		if(ObjectUtil.isNotNull(where)){
			this.where.append(where);
		}
	}

	@Override
	public boolean isSupport(HandlerType hType,Class<?> cls){
		return HandlerType.UPDATE == hType;
	}

	@Override
	public void build(Object obj){
		TableMetaObject metaObject = getMetaObject(obj.getClass());
		TableValueCompare sc = new TableValueCompare(getValueConvert(),obj);
		sql.append(metaObject.getTableName());
		sql.append(" SET ");
		Set<Entry<String,FieldMetaObject>> entrySet = metaObject.getFields().entrySet();
		for(Entry<String,FieldMetaObject> e:entrySet){
			FieldMetaObject val = e.getValue();
			Object value = val.getValue(obj);
			if(val.isIgnore() == false && val.isIdKey() == false){
				sc.setFieldMeta(val);
				if(null != val.getAnnotation() && val.getAnnotation().autoUpdate() == AutoUpdate.CHANGE){
					ObjectUtil.modifyFieldValue(obj,val.getField().getName(),getValueConvert().getRandomValue(val.getType()));
				}
				if(sc.compare(value) == false){
					if(null == value && sqlAspect.discardNull(metaObject,val)){
						continue;
					}
					sql.append(val.getName()).append(" = ").append(sqlAspect.processValue(metaObject,val,value));
					sql.append(",");
				}
			}else{
				if(null != value && val.checkOutreachAction(HandlerType.UPDATE) && null != val.getAnnotation() && val.getAnnotation().relation().length() > 0){
					if(outreachHandlers == null){
						outreachHandlers = new ArrayList<>();
					}
					outreachHandlers.add(new OutreachProvider(obj,val,SqlMapping.getHandler(HandlerType.UPDATE,val.getClass())));
					continue;
				}
			}
		}
		sql.setLength(sql.length() - 1);
		FieldMetaObject idKey = metaObject.getIdKey();
		if(null != idKey){
			if(obj instanceof DataBaseTable){
				sc.setFieldMeta(idKey);
				try{
					addParam(idKey.getName(),sc.getSourceValue());
				}catch(NullPointerException ex){
					addParam(idKey.getName(),idKey.getValue(obj));
				}
			}else{
				addParam(idKey.getName(),idKey.getValue(obj));
			}
		}
	}
}
